summaryrefslogtreecommitdiffstats
path: root/src/common/signal_chain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/signal_chain.cpp')
-rw-r--r--src/common/signal_chain.cpp42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/common/signal_chain.cpp b/src/common/signal_chain.cpp
new file mode 100644
index 000000000..2e4fecc48
--- /dev/null
+++ b/src/common/signal_chain.cpp
@@ -0,0 +1,42 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <dlfcn.h>
+
+#include "common/assert.h"
+#include "common/dynamic_library.h"
+#include "common/scope_exit.h"
+#include "common/signal_chain.h"
+
+namespace Common {
+
+template <typename T>
+T* LookupLibcSymbol(const char* name) {
+#if defined(__BIONIC__)
+ Common::DynamicLibrary provider("libc.so");
+ if (!provider.IsOpen()) {
+ UNREACHABLE_MSG("Failed to open libc!");
+ }
+#else
+ // For other operating environments, we assume the symbol is not overridden.
+ const char* base = nullptr;
+ Common::DynamicLibrary provider(base);
+#endif
+
+ void* sym = provider.GetSymbolAddress(name);
+ if (sym == nullptr) {
+ sym = dlsym(RTLD_DEFAULT, name);
+ }
+ if (sym == nullptr) {
+ UNREACHABLE_MSG("Unable to find symbol {}!", name);
+ }
+
+ return reinterpret_cast<T*>(sym);
+}
+
+int SigAction(int signum, const struct sigaction* act, struct sigaction* oldact) {
+ static auto libc_sigaction = LookupLibcSymbol<decltype(sigaction)>("sigaction");
+ return libc_sigaction(signum, act, oldact);
+}
+
+} // namespace Common